package com.haixee.parkdemo.auth.jwt;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.haixee.parkdemo.auth.enums.AuthScope;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.jackson.io.JacksonDeserializer;
import io.jsonwebtoken.lang.Maps;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;

import java.security.Key;
import java.util.Map;

/**
 * @author RUIFENG GUO
 * 2020/3/25 22:39
 */
public interface JwtOperator {

    String generateJwt(Integer uid);

    String generateJwtWithExtra(Integer uid, AuthScope scope, JwsTokenExtra extra);

    JwsToken getToken(String token);

    String getName();

    long getExpire();

    default JwsToken getJwsToken(String token, Key key) {

        Claims claims = Jwts.parserBuilder()
                .deserializeJsonWith(new JacksonDeserializer(Maps.of("extra", JwsTokenExtra.class).build()))
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();

        Integer uid = claims.get("uid", Integer.class);
        JwsTokenExtra extra = claims.get("extra", JwsTokenExtra.class);
        Byte scope = claims.get("scope", Byte.class);
        long expire = claims.getExpiration().getTime() / 1000;

        return new JwsToken(token, uid, scope, expire, extra);
    }

    default JwsToken parseWithoutValid(String token, Key key) {

        JwsToken jwsToken = new JwsToken();

        try {
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
        } catch (ExpiredJwtException ignored) {
        } catch (JwtException ex) {
            return jwsToken;
        }

        String[] parts = token.split("\\.");

        if (parts.length != 3) {
            return jwsToken;
        }

        // 将jwt claim 解析成json字符串
        String payloadJson = StringUtils.newStringUtf8(Base64.decodeBase64(parts[1]));
        ObjectMapper objectMapper = new ObjectMapper();

        // todo /1000 ?
        try {
            jwsToken = objectMapper.readValue(payloadJson, JwsToken.class);
            if (jwsToken != null && jwsToken.getExp() != 0) {
                jwsToken.setExp(jwsToken.getExp() / 1000);
            }
            Map<String, ?> values = objectMapper.readValue(payloadJson, Map.class);
            for (Map.Entry<String, ?> entry : values.entrySet()) {
                // 获取用户信息
                if ("uid".equals(entry.getKey())) {
                    Integer uid = Integer.parseInt(entry.getValue().toString());
                    jwsToken.setUid(uid);
                    continue;
                }

                // 判断 jwt 是否过期
                if ("exp".equals(entry.getKey())) {
                    Long expire = ((Integer) entry.getValue()).longValue();
                    jwsToken.setExp(expire);
                }

            }
        } catch (JsonProcessingException e) {
            return jwsToken;
        }

        return jwsToken;
    }
}
